#include <linux/kernel.h> /* printk() */
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/vmalloc.h>
//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
//#include <malloc.h>

typedef struct SwapPacket{
	int type;	//typ packetu
	/*
		type:
		1 - hello
		2 - swap-out request
		3 - swap-out reply
		4 - swap-in request
		5 - swap-in reply
	*/

	short int flag_ack; 	//flagy budu bud 0 alebo 1
	short int flag_nack;

	int checksum;	//checksum 4B
	u32 ip;		//ip adresa
	short int network_load; //vytazenie siete, hodnota 0-255
	short int cpu_load;	//vytazenie cpu, hodnota 0-255
	int num_proc;	//pocet procesov, 4B
	int space; 	//priestor na disku 4B (volny, pozadovany, podla typu packetu)
	u32 page_id;	//identifikator stranky
	struct reqtimer* seq_num; 	//sekvecne cislo (alebo ack cislo, podla typu packetu)
	u32 mem_address; //adresa vo fyzickej pamati

	char data[512];	//swapovana stranka
} SwapPacket;

int analyze(char *raw_data, SwapPacket *x){
	unsigned char *byte = raw_data;
	int type;
	int flag_ack;
	int flag_nack;
	int checksum;
	int ip;
	int network_load, cpu_load, num_proc, space;
	int page_id, seq_num, mem_address;
	int i;

	type = ((byte[3]<<24)|(byte[2]<<16)|(byte[1]<<8)|(byte[0]));
	x->type = type;
	//printf("DEBUG: analyze: type: %d\n", type);
	flag_ack = ((byte[5]<<8)|(byte[4]));
	x->flag_ack = flag_ack;
	//printf("DEBUG: analyze: flag_ack: %d\n", flag_ack);
	flag_nack = ((byte[7]<<8)|(byte[6]));
	x->flag_nack = flag_nack;
	//printf("DEBUG: analyze: flag_nack: %d\n", flag_nack);
	checksum = ((byte[11]<<24)|(byte[10]<<16)|(byte[9]<<8)|(byte[8]));
	x->checksum = checksum;
	ip = ((byte[15]<<24)|(byte[14]<<16)|(byte[13]<<8)|(byte[12]));
	x->ip = ip;

	switch(type){
		case 1:		//hello packet
			network_load = ((byte[17]<<8)|(byte[16]));
			x->network_load = network_load;
			cpu_load = ((byte[19]<<8)|(byte[18]));
			x->cpu_load = cpu_load;
			num_proc = ((byte[23]<<24)|(byte[22]<<16)|(byte[21]<<8)|(byte[20]));
			x->num_proc = num_proc;
			space = ((byte[27]<<24)|(byte[26]<<16)|(byte[25]<<8)|(byte[24]));
			x->space = space;
			break;
		case 2:		//swap-out request
		case 3:		//swap-out reply
		case 4:		//swap-in request
		case 5: 	//swap-in reply
			space = ((byte[27]<<24)|(byte[26]<<16)|(byte[25]<<8)|(byte[24]));
			x->space = space;
			page_id = ((byte[31]<<24)|(byte[30]<<16)|(byte[29]<<8)|(byte[28]));
			x->page_id = page_id;
			seq_num = ((byte[35]<<24)|(byte[34]<<16)|(byte[33]<<8)|(byte[32]));
			x->seq_num = (struct reqtimer *) seq_num;
			mem_address = ((byte[39]<<24)|(byte[38]<<16)|(byte[37]<<8)|(byte[36]));
			x->mem_address = mem_address;
			for(i = 0; i < 512; i++){
				x->data[i] = (char) byte[i + 40];
			}
			break;
		default:
			return 1;
			break;
	}
	return 0;
}

int get_int_ip(char *s){
	//printf("get_int_ip: s: %s\n", s);
	unsigned int one, two, three, four, ip;
	unsigned char c_one, c_two, c_three, c_four;
	sscanf(s, "%i.%i.%i.%i", &one, &two, &three, &four);
	//printf("get_int_ip: one: %d\n", one);
	//printf("get_int_ip: two: %d\n", two);
	//printf("get_int_ip: three: %d\n", three);
	//printf("get_int_ip: four: %d\n", four);
	c_one = (unsigned char) one;
	c_two = (unsigned char) two;
	c_three = (unsigned char) three;
	c_four = (unsigned char) four;

	ip = ((c_one << 24)|(c_two << 16)|(c_three << 8)|(c_four));
	//printf("get_int_ip: ip: %d\n", ip);

	return ip;
}

char *get_str_ip(unsigned int ip){
	char *p;
	unsigned int ip_one = (unsigned int) (ip >> 24);
	//printf("%d\n", (unsigned int) ip_one);
	int ip_two = (ip >> 16) & 0xff;
	//printf("%d\n", ip_two);
	int ip_three = (ip >> 8) & 0xff;
	//printf("%d\n", ip_three);
	int ip_four = ip & 0xff;
	//printf("%d\n", ip_four);
	
	p = (char *) vmalloc (15 * sizeof(char));
	sprintf(p, "%i.%i.%i.%i", ip_one, ip_two, ip_three, ip_four);
	return p;
}


/*int backup_main(){
	//vytvorenie raw dat, krore budu poslane sietovym rozhranim klientovi
	SwapPacket x;

	x.type = 1;
	x.flag_ack = 0;
	x.flag_nack = 0;
	x.ip = get_int_ip("192.168.1.72");
	x.checksum = 0;

	x.network_load = 0;
	x.cpu_load = 0;
	x.num_proc = 0;
	
	x.space = 0;
	x.page_id = 0;
	x.seq_num = 0;*/

	/*char *data = (char *) malloc (512 * sizeof(char));
	data = "bla bla bla"; //swapovana stranka
	int i;
	for(i = 0; i < 512; i++){
		x.data[i] = data[i];
	}*/

	/*unsigned char *raw_data = (unsigned char *)&x; //raw_data by malo byt podane funkcii na sietovej vrstve

	//analyza prijatych dat
	SwapPacket rcvd; //v tejto strukture budu spristupnene data
	SwapPacket *rcvd_ptr = &rcvd;
	analyze(raw_data, rcvd_ptr); //rozparsovanie raw dat do struktury
	//data su pristupne
	printk("DEBUG: rcvd: type: %d\n", rcvd.type);
	printk("DEBUG: rcvd: flag_ack: %d\n", rcvd.flag_ack);
	printk("DEBUG: rcvd: flag_nack: %d\n", rcvd.flag_nack);
	printk("DEBUG: rcvd: checksum: %d\n", rcvd.checksum);
	printk("DEBUG: rcvd: ip: %s\n", get_str_ip(rcvd.ip));
	printk("DEBUG: rcvd: network_load: %d\n", rcvd.network_load);
	printk("DEBUG: rcvd: cpu_load: %d\n", rcvd.cpu_load);
	printk("DEBUG: rcvd: num_proc: %d\n", rcvd.num_proc);
	printk("DEBUG: rcvd: space: %d\n", rcvd.space);

	return 0;
}*/

